/* eslint-disable no-param-reassign */
import React, { useState, forwardRef, useImperativeHandle, useEffect } from 'react';
import type { TreeProps } from 'antd';
import { Tree, Button, Space, Popconfirm } from 'antd';
import {
  EditOutlined,
  PlusOutlined,
  MinusOutlined,
  CloseOutlined,
  CheckOutlined,
  SolutionOutlined,
} from '@ant-design/icons';
import MenuModal from './MenuModal';
import { FormattedMessage } from 'umi';
import { iconEnum } from '@/utils/icon';

import { nanoid } from 'nanoid';

import type { EditTreeType } from './data';
import type { FormValType } from './MenuModal/data';

const { TreeNode } = Tree;

type dataProps = {
  editTreeData: EditTreeType[];
  getTreeDate: (data: EditTreeType[]) => void;
  canEditMenu?: boolean; // 是否能编辑菜单，路由和icon的设置
  expandedKeyArr?: string[];
};

const EditTree = (props: TreeProps & dataProps, ref: React.Ref<unknown> | undefined) => {
  const {
    editTreeData,
    getTreeDate,
    canEditMenu = false,
    expandedKeyArr = [],
    ...otherProps
  } = props;
  const [treeData, setTreeData] = useState<EditTreeType[]>(editTreeData);
  const [expandedKeys, setExpandedKeys] = useState<string[]>(expandedKeyArr);
  const [showEditModal, setShowEditModal] = useState<boolean>(false);
  const [itemKey, setItemKey] = useState<string>('');

  useImperativeHandle(ref, () => ({
    onSubmit: () => {
      getTreeDate(treeData);
    },
  }));

  // props触发render
  useEffect(() => {
    setTreeData(editTreeData);
    setExpandedKeys(expandedKeyArr);
  }, [editTreeData, expandedKeyArr]);

  const onExpand = (expandedKeysValue: React.SetStateAction<string[]>) => {
    // 记录折叠的key值
    setExpandedKeys(expandedKeysValue);
  };

  const editNode = (key: any, data: any[]) =>
    data?.forEach(
      (item: { key: any; isEditable: boolean; name: any; defaultValue: any; children: any }) => {
        if (item.key === key) {
          item.isEditable = true;
        } else {
          item.isEditable = false;
        }
        // item.value = item.defaultValue; // 当某节点处于编辑状态，并改变数据，点击编辑其他节点时，此节点变成不可编辑状态，value 需要回退到 defaultvalue
        if (item.children) {
          editNode(key, item.children);
        }
      },
    );

  const addNode = (key: any, data: any[]) =>
    data?.forEach((item: { key: any; children: EditTreeType[] }) => {
      if (item.key === key) {
        if (item.children) {
          item.children.push({
            name: 'default',
            defaultValue: 'default',
            authority: ['admin'],
            key: nanoid(), // 这个 key 应该是唯一的
            parentKey: item.key,
          });
        } else {
          item.children = [];
          item.children.push({
            name: 'default',
            defaultValue: 'default',
            authority: ['admin'],
            key: nanoid(),
            parentKey: item.key,
          });
        }
        return;
      }
      if (item.children) {
        addNode(key, item.children);
      }
    });

  const onAdd = (key: string) => {
    if (expandedKeys.indexOf(key) === -1) {
      expandedKeyArr.push(key);
    }
    setExpandedKeys(expandedKeyArr.slice());

    addNode(key, treeData);
    // useState里数据务必为immutable （不可赋值的对象），所以必须加上slice()返回一个新的数组对象
    setTreeData(treeData.slice());
  };

  const onEdit = (key: any) => {
    editNode(key, treeData);
    setTreeData(treeData.slice());
  };

  const changeNode = (
    key: any,
    name: any,
    data: any[],
    menuDataList?: FormValType & { defaultValue: string },
  ) =>
    data?.forEach((item: EditTreeType) => {
      if (name && item.key === key) {
        item.name = name;
      }
      if (name && item.children) {
        changeNode(key, name, item.children);
      }
      if (menuDataList) {
        if (item.key === key) {
          item.name = menuDataList.name;
          item.defaultValue = menuDataList.defaultValue;
          item.path = menuDataList.path;
          item.icon = menuDataList.icon;
        }
        if (item.children) {
          changeNode(key, null, item.children, menuDataList);
        }
      }
    });

  const onChange = (e: React.ChangeEvent<HTMLInputElement>, key: any) => {
    changeNode(key, e.target.value, treeData);
    setTreeData(treeData.slice());
  };

  const onFinish = async (val: any) => {
    changeNode(itemKey, null, treeData, val);
    setTreeData(treeData.slice());
    if (val) {
      setShowEditModal(false);
    }
  };

  const saveNode = (key: any, data: any[]) =>
    data?.forEach(
      (item: { key: any; defaultValue: any; name: any; children: any; isEditable: boolean }) => {
        if (item.key === key) {
          item.defaultValue = item.name;
        }
        if (item.children) {
          saveNode(key, item.children);
        }
        item.isEditable = false;
      },
    );

  const onSave = (key: any) => {
    saveNode(key, treeData);
    setTreeData(treeData.slice());
  };

  const closeNode = (key: any, defaultValue: any, data: any[]) =>
    data?.forEach((item: { isEditable: boolean; key: any; name: any; children: any }) => {
      item.isEditable = false;
      if (item.key === key) {
        item.name = defaultValue;
      }
      if (item.children) {
        closeNode(key, defaultValue, item.children);
      }
    });

  const onClose = (key: any, defaultValue: any) => {
    closeNode(key, defaultValue, treeData);
    setTreeData(treeData.slice());
  };

  const deleteNode = (key: any, data: any[]) => {
    data?.forEach((item: { key: any; children: any }, index: any) => {
      if (item.key === key) {
        data.splice(index, 1);
        return;
      }
      if (item.children) {
        deleteNode(key, item.children);
      }
    });
  };

  const onDelete = (key: any) => {
    deleteNode(key, treeData);
    setTreeData(treeData.slice());
  };

  const onEditMenu = (key: string) => {
    setItemKey(key);
    setShowEditModal(true);
  };

  const renderTreeNodes = (renderData: any[]) => {
    const nodeArr = renderData?.map(
      (
        item: {
          title: React.ReactNode;
        } & EditTreeType,
      ) => {
        if (item.isEditable && canEditMenu) {
          // eslint-disable-next-line no-param-reassign
          item.title = (
            <div>
              {iconEnum[item.icon as string]}
              <input value={item.name || ('' as any)} onChange={(e) => onChange(e, item.key)} />

              <CloseOutlined
                style={{ marginLeft: 10 }}
                onClick={() => onClose(item.key, item.defaultValue)}
              />

              <CheckOutlined style={{ marginLeft: 10 }} onClick={() => onSave(item.key)} />
            </div>
          );
        } else {
          item.title = (
            <div>
              {iconEnum[item.icon as string]}
              <span style={{ marginLeft: 10 }}>
                <FormattedMessage id={`menu.${item.name}`} defaultMessage={item.name as string} />
              </span>
              <span>
                {canEditMenu && (
                  <>
                    <EditOutlined style={{ marginLeft: 10 }} onClick={() => onEdit(item.key)} />

                    {item.key !== '0' && (
                      <PlusOutlined
                        style={{ marginLeft: 10 }}
                        onClick={() => onAdd(item.key as string)}
                      />
                    )}
                  </>
                )}
                {item.parentKey === '-1'
                  ? null
                  : item.key !== '0' &&
                    canEditMenu && (
                      <Popconfirm
                        placement="top"
                        title="确定删除嘛？子菜单也会被删除哦！"
                        onCancel={() => onDelete(item.key)}
                        cancelButtonProps={{ type: 'primary', danger: true }}
                        okText="取消"
                        cancelText="是的"
                        okType="default"
                      >
                        <MinusOutlined style={{ marginLeft: 10 }} />
                      </Popconfirm>
                    )}
                {canEditMenu && (
                  <SolutionOutlined
                    style={{ marginLeft: 10 }}
                    onClick={() => onEditMenu(item.key as string)}
                  />
                )}
              </span>
            </div>
          );
        }

        if (item.children) {
          return (
            <TreeNode title={item.title} key={item.key} disableCheckbox={item.disableCheckbox}>
              {renderTreeNodes(item.children)}
            </TreeNode>
          );
        }

        return (
          <TreeNode title={item.title} key={item.key} disableCheckbox={item.disableCheckbox} />
        );
      },
    );

    return nodeArr;
  };

  // 添加一级菜单
  const addFristNode = (addData: EditTreeType[]) => () => {
    // treeData.push({
    //   value: 'default',
    //   key: nanoid(),
    //   defaultValue: "default"
    // })
    setTreeData([
      ...addData,
      {
        name: 'default',
        key: nanoid(),
        defaultValue: 'default',
      },
    ]);
  };

  const handleCancel = () => {
    setShowEditModal(false);
  };

  return (
    <div>
      <Space direction="vertical">
        {canEditMenu && (
          <Button type="primary" icon={<PlusOutlined />} onClick={addFristNode(treeData)}>
            添加一级菜单
          </Button>
        )}
        <Tree expandedKeys={expandedKeys} onExpand={onExpand as any} {...otherProps}>
          {renderTreeNodes(treeData)}
        </Tree>
      </Space>
      <MenuModal
        showEditModal={showEditModal}
        footer={null}
        onCancel={handleCancel}
        onFinish={onFinish}
        treeData={treeData}
        itemKey={itemKey}
      />
    </div>
  );
};

export default forwardRef(EditTree);
